package com.geega.geetest.geetest;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.geega.geetest.util.RedisUtil;
import com.geega.geetest.util.IpUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;

import static com.alibaba.fastjson.JSON.parseObject;

@Component
public class CaptchaService {

    @Value("${geetest.cid}")
    private String cid;

    @Value("${geetest.key}")
    private String key;

    @Value("${geetest.static-server}")
    private String staticServer;

    @Value("${geetest.api-url}")
    private String apiUrl;

    private final RedisUtil redisUtil;

    private final HttpServletRequest request;

    public CaptchaService(RedisUtil redisUtil, HttpServletRequest request) {
        this.redisUtil = redisUtil;
        this.request = request;
    }

    /**
     * 滑块验证码初始化
     */
    public JSONObject initCaptcha() {
        GeetestLib gtSdk = new GeetestLib(cid, key);
        //自定义参数,可选择添加
        HashMap<String, String> param = new HashMap<>();
        ////网站用户id
        String userid = "test";
        param.put("user_id", userid); //网站用户id
        //web:电脑上的浏览器；h5:手机上的浏览器，包括移动应用内完全内置的web_view；native：通过原生SDK植入APP应用的方式
        param.put("client_type", "web");
        //传输用户请求验证时所携带的IP
        param.put("ip_address", IpUtil.getIpAddress(request));
        //进行验证预处理
        JSONObject configJson = new JSONObject();
        configJson.put("static_servers", staticServer);
        configJson.put("apiUrl", apiUrl);
        String gtServerStatus = gtSdk.preProcess(param, configJson);
        int status = 1;
        try {
            status = parseObject(gtServerStatus).getInteger("status");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        String resStr = gtSdk.getResponseStr();
        JSONObject respJson = parseObject(resStr);
        JSONObject dataJson = respJson.getJSONObject("data");
        String challenge = dataJson.getString(GeetestLib.fn_geetest_challenge);
        //将服务器状态设置到session中, api2会取出使用，格外注意session的存取和分布式环境下的应用场景
        redisUtil.set(GeetestLib.fn_geetest_challenge + ":" + challenge, status + "", 600L);
        return respJson;
    }


    /**
     * 返回滑块验证码是否校验通过
     */
    public Boolean verify(String challenge) {
        GeetestLib gtSdk = new GeetestLib(cid, key);
        gtSdk.gtlog("challenge:" + challenge);
        int gtServerStatusCode = 0;
        String redisKey = GeetestLib.fn_geetest_challenge + ":" + challenge;
        //从session中获取gt-server状态
        try {
            Object o = redisUtil.get(redisKey);
            if (o == null) {
                return false;
            }
            gtServerStatusCode = Integer.parseInt(o.toString());
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        //自定义参数,可选择添加
        HashMap<String, String> param = new HashMap<>();
        //网站用户id
        //web:电脑上的浏览器；h5:手机上的浏览器，包括移动应用内完全内置的web_view；native：通过原生SDK植入APP应用的方式
        param.put("client_type", "web");
        //传输用户请求验证时所携带的IP
        param.put("ip_address", IpUtil.getIpAddress(request));
        String gtResult = "";

        if (gtServerStatusCode == 0) {
            //gt-server正常，向gt-server进行二次验证
            JSONObject configJson = new JSONObject();
            configJson.put("static_servers", staticServer);
            configJson.put("apiUrl", apiUrl);
            gtResult = gtSdk.enhencedValidateRequest(challenge, param, configJson);
        } else {
            // gt-server非正常情况下，进行failback模式验证
            gtSdk.gtlog("failback:use your own server captcha validate");
            gtResult = gtSdk.failbackValidateRequest(challenge);
            gtSdk.gtlog("fail gtResult:" + gtResult);
        }
        JSONObject gtResultJson = parseObject(gtResult);
        JSONObject dataJson = gtResultJson.getJSONObject("data");
        String result = dataJson.getString("result");
        redisUtil.remove(redisKey);
        return "success".equals(result);
    }

    public void check(Boolean capEnable, String challenge){
        if(capEnable != null && capEnable){
            Assert.isTrue(this.verify(challenge), "滑块验证码错误");
        }else {
            Assert.isTrue(true, "滑块验证码错误");
        }
    }
}
